#pragma once 

#include <vector>
#include <string>
#include <functional>
/**
 * | prependable |  readable  bytes |  writeable bytes |
 *   0 <=  readerIndex <= writerIndex <= size
 * 
 */
class Buffer{
public:
    static const size_t kCheapPrepend = 8;
    static const size_t kInitialSize = 1024;

    explicit Buffer(size_t initialSize = kInitialSize)
    : buffer_(kCheapPrepend + initialSize)
    , readIndex_(kCheapPrepend)
    , writeIndex_(kCheapPrepend){}

    size_t readableBytes() const{
        return writeIndex_ - readIndex_;
    }

    size_t writeableBytes() const{
        return buffer_.size() - writeIndex_;
    }

    size_t prependableBytes() const{
        return readIndex_;
    }

    // 返回 缓冲区中可读数据的起始地址 
    const char* peek() {
        return begin() + readIndex_;
    }

    void retrive(size_t len){
        if(len < readableBytes()){
            readIndex_ += len;
        }else{
            retriveAll();
        }
    }


    // 读取完毕， 复位
    void retriveAll(){
        readIndex_ = writeIndex_ = kCheapPrepend;
    }

    std::string retriveAllAsString(){
        return retriveAsString(readableBytes());
    }

    std::string retriveAsString(size_t len){

        std::string result(peek(), len);
        retrive(len);
        return result;
    }

    void makeSpace(size_t len){
        if(writeableBytes() + prependableBytes() < len + kCheapPrepend){
            buffer_.resize(writeIndex_ + len);
        }else{
            size_t readable = readableBytes();
            std::copy(begin() + readIndex_,
                begin() + writeIndex_,
                begin() + kCheapPrepend);
                readIndex_ = kCheapPrepend;
                writeIndex_ = readIndex_ + readable;
        };
    }

    void ensureWriteableBytes(size_t len){
        if(writeableBytes() < len){
            makeSpace(len);
        }
    }
    // 把[data, data+len ] 内存的数据添加到缓冲区当中
    void append(char* data, size_t len){
        ensureWriteableBytes(len);

        std::copy(data, data+len, beginWrite());
        writeIndex_ += len;
    }

    char* beginWrite(){
        return begin() + writeIndex_;
    }

    // 从fd
    ssize_t readFd(int fd, int* saveErrno);
    ssize_t writeFd(int fd, int* saveErrno);

    

private:
    char* begin() {
        return & *buffer_.begin();
    }

    const char* cbegin() {
        return & *buffer_.begin();
    }
    std::vector<char> buffer_;
    size_t readIndex_;
    size_t writeIndex_;
};